home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 23 / AACD 23.iso / AACD / Online / opennap / privmsg.c < prev    next >
C/C++ Source or Header  |  2001-06-08  |  15KB  |  515 lines

  1. /* Copyright (C) 2000-1 drscholl@users.sourceforge.net
  2.    This is free software distributed under the terms of the
  3.    GNU Public License.  See the file COPYING for details.
  4.  
  5.    $Id: privmsg.c,v 1.56 2001/02/15 08:39:45 drscholl Exp $ */
  6.  
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #ifndef WIN32
  10. #include <unistd.h>
  11. #endif
  12. #include <string.h>
  13. #include "opennap.h"
  14. #include "debug.h"
  15.  
  16. /* loopback command for allowing mods using the windows client to execute
  17.    opennap comamnds */
  18. static void
  19. operserv (CONNECTION * con, char *pkt)
  20. {
  21.     char   *cmd = next_arg (&pkt);
  22.     unsigned short tag, len;
  23.     char    ch = 0;
  24.  
  25.     if (!cmd)
  26.     return;
  27.     if (!strcasecmp ("chanlevel", cmd))
  28.     tag = MSG_CLIENT_CHANNEL_LEVEL;
  29.     else if (!strcasecmp ("links", cmd))
  30.     tag = MSG_CLIENT_LINKS;
  31.     else if (!strcasecmp ("stats", cmd))
  32.     tag = MSG_CLIENT_USAGE_STATS;
  33.     else if (!strcasecmp ("connect", cmd))
  34.     tag = MSG_CLIENT_CONNECT;
  35.     else if (!strcasecmp ("disconnect", cmd))
  36.     tag = MSG_CLIENT_DISCONNECT;
  37.     else if (!strcasecmp ("killserver", cmd))
  38.     tag = MSG_CLIENT_KILL_SERVER;
  39.     else if (!strcasecmp ("nuke", cmd))
  40.     tag = MSG_CLIENT_NUKE;
  41.     else if (!strcasecmp ("register", cmd))
  42.     tag = MSG_CLIENT_REGISTER_USER;
  43.     else if (!strcasecmp ("chanlimit", cmd))
  44.     tag = MSG_CLIENT_CHANNEL_LIMIT;
  45.     else if (!strcasecmp ("kick", cmd))
  46.     tag = MSG_CLIENT_KICK_USER;
  47.     else if (!strcasecmp ("usermode", cmd))
  48.     tag = MSG_CLIENT_USER_MODE;
  49.     else if (!strcasecmp ("config", cmd))
  50.     tag = MSG_CLIENT_SERVER_CONFIG;
  51.     else if (!strcasecmp ("reconfig", cmd))
  52.     tag = MSG_CLIENT_SERVER_RECONFIG;
  53.     else if (!strcasecmp ("cban", cmd))
  54.     tag = MSG_CLIENT_CHANNEL_BAN;
  55.     else if (!strcasecmp ("cunban", cmd))
  56.     tag = MSG_CLIENT_CHANNEL_UNBAN;
  57.     else if (!strcasecmp ("cbanlist", cmd))
  58.     tag = MSG_CLIENT_CHANNEL_BAN_LIST;
  59.     else if (!strcasecmp ("cbanclear", cmd))
  60.     tag = MSG_CLIENT_CHANNEL_CLEAR_BANS;
  61.     else if (!strcasecmp ("clearchan", cmd))
  62.     tag = MSG_CLIENT_CLEAR_CHANNEL;
  63.     else if (!strcasecmp ("cloak", cmd))
  64.     tag = MSG_CLIENT_CLOAK;
  65.     else if (!strcasecmp ("op", cmd))
  66.     tag = MSG_CLIENT_OP;
  67.     else if (!strcasecmp ("oplist", cmd))
  68.     tag = MSG_CLIENT_OP;    /* deprecated, but this should work as expected */
  69.     else if (!strcasecmp ("deop", cmd))
  70.     tag = MSG_CLIENT_DEOP;
  71.     else if (!strcasecmp ("rehash", cmd))
  72.     tag = MSG_CLIENT_REHASH;
  73.     else if (!strcasecmp ("server", cmd))
  74.     tag = MSG_CLIENT_WHICH_SERVER;
  75.     else if (!strcasecmp ("redirect", cmd))
  76.     tag = MSG_CLIENT_REDIRECT;
  77.     else if (!strcasecmp ("cycle", cmd))
  78.     tag = MSG_CLIENT_CYCLE;
  79.     else if (!strcasecmp ("whowas", cmd))
  80.     tag = MSG_CLIENT_WHO_WAS;
  81.     else if (!strcasecmp ("help", cmd))
  82.     {
  83.     send_cmd (con, MSG_CLIENT_PRIVMSG, "OperServ Help for OperServ:");
  84.     send_cmd (con, MSG_CLIENT_PRIVMSG,
  85.           "OperServ cloak - toggle invisibility to normal users");
  86.     send_cmd (con, MSG_CLIENT_PRIVMSG,
  87.           "OperServ config <variable> [value] - query/set server configuration");
  88.     send_cmd (con, MSG_CLIENT_PRIVMSG,
  89.           "OperServ connect <server> [remote_server] - link a server");
  90.     send_cmd (con, MSG_CLIENT_PRIVMSG,
  91.           "OperServ cycle <nick> <host> - request client reconnect to metaserver <host>");
  92.     send_cmd (con, MSG_CLIENT_PRIVMSG,
  93.           "OperServ disconnect <server> - delink a server");
  94.     send_cmd (con, MSG_CLIENT_PRIVMSG,
  95.           "OperServ help - display this help message");
  96.     send_cmd (con, MSG_CLIENT_PRIVMSG,
  97.           "OperServ killserver [server] - cause a server to shut down");
  98.     send_cmd (con, MSG_CLIENT_PRIVMSG, "OperServ links");
  99.     send_cmd (con, MSG_CLIENT_PRIVMSG,
  100.           "OperServ nuke <nick> - unregister a nickname");
  101.     send_cmd (con, MSG_CLIENT_PRIVMSG,
  102.           "OperServ reconfig <variable> - reset server configuration variable");
  103.     send_cmd (con, MSG_CLIENT_PRIVMSG,
  104.           "OperServ redirect <nick> <host> <port> - request client connect to server <host>:<port>");
  105.     send_cmd (con, MSG_CLIENT_PRIVMSG, "OperServ register");
  106.     send_cmd (con, MSG_CLIENT_PRIVMSG,
  107.           "OperServ rehash [server] - cause server to reload its config files");
  108.     send_cmd (con, MSG_CLIENT_PRIVMSG,
  109.           "OperServ stats - display server stats");
  110.     send_cmd (con, MSG_CLIENT_PRIVMSG, "OperServ usermode");
  111.     send_cmd (con, MSG_CLIENT_PRIVMSG,
  112.           "OperServ whowas <nick> - display whois info for a recently logged out client");
  113.     send_cmd (con, MSG_CLIENT_PRIVMSG,
  114.           "OperServ END of help for OperServ");
  115.     return;
  116.     }
  117.     else
  118.     {
  119.     send_cmd (con, MSG_SERVER_NOSUCH, "Unknown OperServ command: %s",
  120.           cmd);
  121.     return;
  122.     }
  123.     if (pkt)
  124.     len = strlen (pkt);
  125.     else
  126.     {
  127.     /* most of the handler routines expect `pkt' to be non-NULL so pass
  128.        a dummy value here */
  129.     pkt = &ch;
  130.     len = 0;
  131.     }
  132.     dispatch_command (con, tag, len, pkt);
  133. }
  134.  
  135. static void
  136. chanserv (CONNECTION * con, char *pkt)
  137. {
  138.     char   *cmd = next_arg (&pkt);
  139.     unsigned short tag, len;
  140.     char    ch = 0;
  141.  
  142.     if (!cmd)
  143.     return;
  144.     if (!strcasecmp ("ban", cmd))
  145.     tag = MSG_CLIENT_CHANNEL_BAN;
  146.     else if (!strcasecmp ("unban", cmd))
  147.     tag = MSG_CLIENT_CHANNEL_UNBAN;
  148.     else if (!strcasecmp ("banclear", cmd))
  149.     tag = MSG_CLIENT_CHANNEL_CLEAR_BANS;
  150.     else if (!strcasecmp ("banlist", cmd))
  151.     tag = MSG_CLIENT_CHANNEL_BAN_LIST;
  152.     else if (!strcasecmp ("clear", cmd))
  153.     tag = MSG_CLIENT_CLEAR_CHANNEL;
  154.     else if (!strcasecmp ("kick", cmd))
  155.     tag = MSG_CLIENT_KICK;
  156.     else if (!strcasecmp ("oplist", cmd))    /* deprecated, but should work */
  157.     tag = MSG_CLIENT_OP;
  158.     else if (!strcasecmp ("topic", cmd))
  159.     tag = MSG_SERVER_TOPIC;
  160.     else if (!strcasecmp ("limit", cmd))
  161.     tag = MSG_CLIENT_CHANNEL_LIMIT;
  162.     else if (!strcasecmp ("drop", cmd))
  163.     tag = MSG_CLIENT_DROP_CHANNEL;
  164.     else if (!strcasecmp ("op", cmd))
  165.     tag = MSG_CLIENT_OP;
  166.     else if (!strcasecmp ("deop", cmd))
  167.     tag = MSG_CLIENT_DEOP;
  168.     else if (!strcasecmp ("wallop", cmd))
  169.     tag = MSG_CLIENT_CHANNEL_WALLOP;
  170.     else if (!strcasecmp ("invite", cmd))
  171.     tag = MSG_CLIENT_CHANNEL_INVITE;
  172.     else if (!strcasecmp ("mode", cmd))
  173.     tag = MSG_CLIENT_CHANNEL_MODE;
  174.     else if (!strcasecmp ("muzzle", cmd))
  175.     tag = MSG_CLIENT_CHANNEL_MUZZLE;
  176.     else if (!strcasecmp ("unmuzzle", cmd))
  177.     tag = MSG_CLIENT_CHANNEL_UNMUZZLE;
  178.     else if (!strcasecmp ("unvoice", cmd))
  179.     tag = MSG_CLIENT_CHANNEL_UNVOICE;
  180.     else if (!strcasecmp ("voice", cmd))
  181.     tag = MSG_CLIENT_CHANNEL_VOICE;
  182.     else if (!strcasecmp ("level", cmd))
  183.     tag = MSG_CLIENT_SET_CHAN_LEVEL;
  184.     else if (!strcasecmp ("help", cmd))
  185.     {
  186.     send_cmd (con, MSG_CLIENT_PRIVMSG,
  187.           "ChanServ HELP for ChanServ commands:");
  188.     send_cmd (con, MSG_CLIENT_PRIVMSG,
  189.           "ChanServ ban <channel> <user> [\"reason\"]");
  190.     send_cmd (con, MSG_CLIENT_PRIVMSG,
  191.           "ChanServ banclear <channel> - clear all bans");
  192.     send_cmd (con, MSG_CLIENT_PRIVMSG, "ChanServ banlist <channel>");
  193.     send_cmd (con, MSG_CLIENT_PRIVMSG,
  194.           "ChanServ clear <channel> - kick all users out of channel");
  195.     send_cmd (con, MSG_CLIENT_PRIVMSG,
  196.           "ChanServ deop <channel> [user [user ...]]");
  197.     send_cmd (con, MSG_CLIENT_PRIVMSG, "ChanServ help");
  198.     send_cmd (con, MSG_CLIENT_PRIVMSG,
  199.           "ChanServ invite <channel> <user>");
  200.     send_cmd (con, MSG_CLIENT_PRIVMSG,
  201.           "ChanServ kick <channel> <user> [\"reason\"]");
  202.     send_cmd (con, MSG_CLIENT_PRIVMSG,
  203.           "ChanServ level <channel> [level] - display/set min user level required to join");
  204.     send_cmd (con, MSG_CLIENT_PRIVMSG,
  205.           "ChanServ limit <channel> [number] - set max number of users");
  206.     send_cmd (con, MSG_CLIENT_PRIVMSG,
  207.           "ChanServ mode <channel> [mode [mode ...]]");
  208.     send_cmd (con, MSG_CLIENT_PRIVMSG,
  209.           "ChanServ muzzle <channel> <user>");
  210.     send_cmd (con, MSG_CLIENT_PRIVMSG,
  211.           "ChanServ op <channel> [user [user ...] - display/set channel operators");
  212.     send_cmd (con, MSG_CLIENT_PRIVMSG,
  213.           "ChanServ topic <channel> [topic] - display/set channel topic");
  214.     send_cmd (con, MSG_CLIENT_PRIVMSG, "ChanServ unban <channel>");
  215.     send_cmd (con, MSG_CLIENT_PRIVMSG,
  216.           "ChanServ unmuzzle <channel> <user>");
  217.     send_cmd (con, MSG_CLIENT_PRIVMSG,
  218.           "ChanServ unvoice <channel> [user [user ...]]");
  219.     send_cmd (con, MSG_CLIENT_PRIVMSG,
  220.           "ChanServ voice <channel> [user [user ...]]");
  221.     send_cmd (con, MSG_CLIENT_PRIVMSG,
  222.           "ChanServ wallop <channel> <text> - send message to all channel operators");
  223.     return;
  224.     }
  225.     else
  226.     {
  227.     send_cmd (con, MSG_CLIENT_PRIVMSG, "ChanServ Unknown command");
  228.     return;
  229.     }
  230.     if (pkt)
  231.     len = strlen (pkt);
  232.     else
  233.     {
  234.     /* most of the handler routines expect `pkt' to be non-NULL so pass
  235.        a dummy value here */
  236.     pkt = &ch;
  237.     len = 0;
  238.     }
  239.     dispatch_command (con, tag, len, pkt);
  240. }
  241.  
  242. static void
  243. nickserv (CONNECTION * con, char *pkt)
  244. {
  245.     char   *cmd = next_arg (&pkt);
  246.     char   *nick;
  247.     char   *pass;
  248.     USER   *user;
  249.     USERDB *db;
  250.  
  251.     if (!cmd)
  252.     return;
  253.     if (!strcasecmp ("ghost", cmd))
  254.     {
  255.     nick = next_arg (&pkt);
  256.     pass = next_arg (&pkt);
  257.     if (!nick || !pass)
  258.     {
  259.         send_cmd (con, MSG_CLIENT_PRIVMSG,
  260.               "NickServ Missing argument(s)");
  261.         return;
  262.     }
  263.     user = hash_lookup (Users, nick);
  264.     if (!user)
  265.     {
  266.         send_cmd (con, MSG_CLIENT_PRIVMSG, "NickServ No such user");
  267.         return;
  268.     }
  269.     db = hash_lookup (User_Db, user->nick);
  270.     if (!db)
  271.     {
  272.         send_cmd (con, MSG_CLIENT_PRIVMSG,
  273.               "NickServ Nick is not registered");
  274.         return;
  275.     }
  276.     if (check_pass (db->password, pass))
  277.     {
  278.         send_cmd (con, MSG_CLIENT_PRIVMSG, "NickServ Invalid password");
  279.         return;
  280.     }
  281.     kill_user_internal (0, user, Server_Name, 0, "ghosted by %s",
  282.                 con->user->nick);
  283.     }
  284.     else if (!strcasecmp ("register", cmd))
  285.     {
  286.     db = hash_lookup (User_Db, con->user->nick);
  287.     if (db)
  288.     {
  289.         send_cmd (con, MSG_CLIENT_PRIVMSG,
  290.               "NickServ your nick is already registered");
  291.         return;
  292.     }
  293.     db = create_db (con->user);
  294.     if (!db)
  295.         return;
  296.     hash_add (User_Db, db->nick, db);
  297.     send_cmd (con, MSG_CLIENT_PRIVMSG,
  298.           "NickServ your nick has successfully been registered");
  299.  
  300.     /* pass this on to our peer servers so it gets registered everywhere */
  301.     pass_message_args (con, MSG_CLIENT_REGISTER_USER,
  302.                ":%s %s %s unknown User", Server_Name, db->nick,
  303.                con->user->pass);
  304.     }
  305.     else if (!strcasecmp ("usermode", cmd))
  306.     user_mode_cmd (con, MSG_CLIENT_USER_MODE, 0, pkt);
  307.     else if (!strcasecmp ("nuke", cmd))
  308.     {
  309.     }
  310.     else if (!strcasecmp ("help", cmd))
  311.     {
  312.     send_cmd (con, MSG_CLIENT_PRIVMSG, "NickServ NickServ commands:");
  313.     send_cmd (con, MSG_CLIENT_PRIVMSG,
  314.           "NickServ ghost <nick> <pass> - kill your ghost");
  315.     send_cmd (con, MSG_CLIENT_PRIVMSG,
  316.           "NickServ register <pass> - register your nickname");
  317.     send_cmd (con, MSG_CLIENT_PRIVMSG,
  318.         "NickServ server <nick> - display which server a user is on");
  319.     send_cmd (con, MSG_CLIENT_PRIVMSG,
  320.           "NickServ usermode [flags] - display/set your user mode");
  321.     }
  322.     else if (!strcasecmp ("server", cmd))
  323.     which_server (con, MSG_CLIENT_WHICH_SERVER, 0, pkt);
  324.     else
  325.     send_cmd (con, MSG_CLIENT_PRIVMSG, "NickServ Unknown command");
  326. }
  327.  
  328. /* handles private message commands */
  329. /* [ :<nick> ] <user> <text> */
  330. HANDLER (privmsg)
  331. {
  332.     char   *ptr;
  333.     USER   *sender, *user /* recip */ ;
  334.  
  335.     (void) tag;
  336.     (void) len;
  337.     ASSERT (validate_connection (con));
  338.  
  339.     ptr = pkt;            /* save the start offset of pkt for length check */
  340.     if (pop_user (con, &pkt, &sender) != 0)
  341.     return;
  342.     ASSERT (validate_user (sender));
  343.  
  344.     /* prevent DoS attack againt windows napster client */
  345.     if (len - (pkt - ptr) > 180)
  346.     {
  347.     log ("privmsg(): truncated %d byte message from %s", len,
  348.          sender->nick);
  349.     pkt[180] = 0;
  350.     }
  351.  
  352.     /* check to see if the recipient of the message is local */
  353.     ptr = next_arg_noskip (&pkt);
  354.     if (!pkt)
  355.     {
  356.     unparsable (con);
  357.     return;
  358.     }
  359.  
  360.     if (ISUSER (con))
  361.     {
  362.     if (sender->level > LEVEL_USER && !strcasecmp (ptr, "operserv"))
  363.     {
  364.         operserv (con, pkt);
  365.         return;
  366.     }
  367.     if (!strcasecmp ("chanserv", ptr))
  368.     {
  369.         chanserv (con, pkt);
  370.         return;
  371.     }
  372.     if (!strcasecmp ("nickserv", ptr))
  373.     {
  374.         nickserv (con, pkt);
  375.         return;
  376.     }
  377.     }
  378.  
  379.     /* find the recipient */
  380.     user = hash_lookup (Users, ptr);
  381.     if (!user)
  382.     {
  383.     nosuchuser (con);
  384.     return;
  385.     }
  386.  
  387.     /*  locally connected user */
  388.     if (ISUSER (user->con))
  389.     {
  390.     /* check if the user wishes to receive msgs */
  391.     if ((user->con->uopt->usermode & MSGLOG_MODE) == 0)
  392.     {
  393.         send_user (sender, MSG_SERVER_NOSUCH, "%s is unavailable",
  394.                user->nick);
  395.     }
  396.     /* check to make sure this user is not ignored */
  397.     else if (!is_ignoring (user->con->uopt->ignore, sender->nick))
  398.     {
  399.         /* reconstitute the message */
  400.         send_cmd (user->con, MSG_CLIENT_PRIVMSG, "%s %s", sender->nick,
  401.               pkt);
  402.     }
  403.     else
  404.     {
  405.         /* notify the sender they are being ignored */
  406.         send_user (sender, MSG_SERVER_NOSUCH, "%s is ignoring you",
  407.                user->nick);
  408.     }
  409.     }
  410.     else
  411.     {
  412.     /* pass the message on to our peers since the recipient isn't
  413.        local.  we know which server the client is behind, so we just
  414.        need to send one copy */
  415.     ASSERT (user->con->class == CLASS_SERVER);
  416.     send_cmd (user->con, MSG_CLIENT_PRIVMSG, ":%s %s %s",
  417.           sender->nick, user->nick, pkt);
  418.     }
  419. }
  420.  
  421. /* 320
  422.    list ignored users */
  423. HANDLER (ignore_list)
  424. {
  425.     int     n = 0;
  426.     LIST   *list;
  427.  
  428.     (void) len;
  429.     (void) pkt;
  430.     ASSERT (validate_connection (con));
  431.     CHECK_USER_CLASS ("ignore_list");
  432.     for (list = con->uopt->ignore; list; list = list->next, n++)
  433.     send_cmd (con, MSG_SERVER_IGNORE_ENTRY /* 321 */ , "%s", list->data);
  434.     send_cmd (con, tag, "%d", n);
  435. }
  436.  
  437. /*  322 <user>
  438.     add user to ignore list */
  439. HANDLER (ignore)
  440. {
  441.     LIST   *list;
  442.  
  443.     (void) len;
  444.     ASSERT (validate_connection (con));
  445.     CHECK_USER_CLASS ("ignore_add");
  446.     if (invalid_nick (pkt))
  447.     {
  448.     invalid_nick_msg (con);
  449.     return;
  450.     }
  451.     /*ensure that this user is not already on the ignore list */
  452.     for (list = con->uopt->ignore; list; list = list->next)
  453.     if (!strcasecmp (pkt, list->data))
  454.     {
  455.         send_cmd (con, MSG_SERVER_ALREADY_IGNORED, "%s", pkt);
  456.         return;        /*already added */
  457.     }
  458.     if (Max_Ignore > 0 && list_count (con->uopt->ignore) > Max_Ignore)
  459.     {
  460.     send_cmd (con, MSG_SERVER_NOSUCH,
  461.           "ignore list is limited to %d users", Max_Ignore);
  462.     return;
  463.     }
  464.     list = MALLOC (sizeof (LIST));
  465.     list->data = STRDUP (pkt);
  466.     list->next = con->uopt->ignore;
  467.     con->uopt->ignore = list;
  468.     send_cmd (con, tag, "%s", pkt);
  469. }
  470.  
  471. /* 323 <user>
  472.    unignore user */
  473. HANDLER (unignore)
  474. {
  475.     LIST  **list, *tmpList;
  476.  
  477.     (void) len;
  478.     ASSERT (validate_connection (con));
  479.     CHECK_USER_CLASS ("ignore_add");
  480.     if (invalid_nick (pkt))
  481.     {
  482.     invalid_nick_msg (con);
  483.     return;
  484.     }
  485.     for (list = &con->uopt->ignore; *list; list = &(*list)->next)
  486.     {
  487.     if (!strcasecmp (pkt, (*list)->data))
  488.     {
  489.         send_cmd (con, tag, "%s", pkt);
  490.         tmpList = *list;
  491.         *list = (*list)->next;
  492.         FREE (tmpList->data);
  493.         FREE (tmpList);
  494.         return;
  495.     }
  496.     }
  497.     send_cmd (con, MSG_SERVER_NOT_IGNORED /* 324 */ , "%s", pkt);
  498. }
  499.  
  500. /* 326
  501.    clear user's ignore list */
  502. HANDLER (clear_ignore)
  503. {
  504.     int     n;
  505.  
  506.     (void) len;
  507.     (void) pkt;
  508.     ASSERT (validate_connection (con));
  509.     CHECK_USER_CLASS ("clear_ignore");
  510.     n = list_count (con->uopt->ignore);
  511.     list_free (con->uopt->ignore, free_pointer);
  512.     con->uopt->ignore = 0;
  513.     send_cmd (con, tag, "%d", n);
  514. }
  515.